module ioFileMod
!---------------------------------------------------------------------
!
! Purpose:
!
!	Input/Output file manipulations. Mind file on archival system, or local
!	disk etc.
!
! Author: Mariana Vertenstein
!
!---------------------------------------------------------------------
 
   use shr_kind_mod,     only: r8 => shr_kind_r8
   use cam_abortutils,   only: endrun
   use spmd_utils,       only: masterproc
   use cam_logfile,      only: iulog

   implicit none

!--------------------------------------------------------------------------
! Public interfaces
!--------------------------------------------------------------------------

   private

   public getfil      ! Get file from archive
   public opnfil      ! Open file

!--------------------------------------------------------------------------
! Private interfaces
!--------------------------------------------------------------------------

!=======================================================================
   contains
!=======================================================================
 
subroutine getfil(fulpath, locfn, iflag, lexist)
 
   ! --------------------------------------------------------------------
   ! Determine whether file is on local disk.
   ! . first check current working directory
   ! . next check full pathname[fulpath] on disk
   ! . by default, abort if file not found.  Setting optional iflag arg
   !   to 1 overrides this behavior, and in that case the optional lexist
   !   arg is used to return status of whether the file was found or not.
   ! --------------------------------------------------------------------
 
   ! ------------------------ arguments -----------------------------------
   character(len=*), intent(in)   :: fulpath ! full pathname on local disk
   character(len=*), intent(out)  :: locfn   ! local file name if found in working directory,
                                             ! set to fulpath if not found in working dir.
   integer, optional, intent(in)  :: iflag   ! set iflag=1 to return control to caller if
                                             ! file not found.  default is to abort.
   logical, optional, intent(out) :: lexist  ! When iflag=1 then getfil will return whether the
                                             ! file is found or not.  This flag is set .true.
                                             ! if the file is found, otherwise .false.
 
   ! ------------------------ local variables ---------------------------
   integer :: i               ! loop index
   integer :: klen            ! length of fulpath character string
   integer :: maxlen          ! length of locfn input variable
   integer :: ierr            ! error status
   logical :: lexist_in       ! true if local file exists
   logical :: abort_on_failure
   ! --------------------------------------------------------------------
 
   abort_on_failure = .true.
   if (present(iflag)) then
      if (iflag==1) abort_on_failure = .false.
   end if
   maxlen = len(locfn)

   ! first check if file is in current working directory.

   ! get local file name from full name: start at end. look for first "/"
 
   klen = len_trim(fulpath)
   i = index(fulpath, '/', back=.true.)

   if ((klen-i) > maxlen) then
      if (abort_on_failure) then
         call endrun('(GETFIL): local filename variable is too short for path length')
      else
         if (masterproc) write(iulog,*) '(GETFIL): local filename variable is too short for path length',klen-i,maxlen
         if (present(lexist)) lexist = .false.
         return
      end if
   end if

   locfn = fulpath(i+1:klen)
   if (len_trim(locfn) == 0) then
      call endrun ('(GETFIL): local filename has zero length')
   else if (masterproc) then
      write(iulog,*)'(GETFIL): attempting to find local file ', trim(locfn)
   end if
 
   inquire(file=locfn, exist=lexist_in)
   if (present(lexist)) lexist = lexist_in
   if (lexist_in) then
      if (masterproc) write(iulog,*) '(GETFIL): using ',trim(locfn), ' in current working directory'
      return
   end if
 
   ! second check for full pathname on disk
 
   if (klen > maxlen) then
      if (abort_on_failure) then
         call endrun('(GETFIL): local filename variable is too short for path length')
      else
         if (masterproc) write(iulog,*) '(GETFIL): local filename variable is too short for path length',klen,maxlen
         if (present(lexist)) lexist = .false.
         return
      end if
   end if

   locfn = trim(fulpath)
   inquire(file=locfn, exist=lexist_in)
   if (present(lexist)) lexist = lexist_in
   if (lexist_in) then
      if (masterproc) write(iulog,*)'(GETFIL): using ',trim(fulpath)
      return
   else
      if (masterproc) write(iulog,*)'(GETFIL): all tries to get file have been unsuccessful: ',trim(fulpath)
      if (abort_on_failure) then
         call endrun ('GETFIL: FAILED to get '//trim(fulpath))
      else
         return
      endif
   endif

end subroutine getfil
 
!=======================================================================
 
 
   subroutine opnfil (locfn, iun, form, status)
 
!-----------------------------------------------------------------------
! open file locfn in unformatted or formatted form on unit iun
!-----------------------------------------------------------------------
 
! ------------------------ input variables ---------------------------
   character(len=*), intent(in):: locfn  !file name
   integer, intent(in):: iun             !fortran unit number
   character(len=1), intent(in):: form   !file format: u = unformatted. f = formatted
   character(len=*), optional, intent(in):: status !file status
! --------------------------------------------------------------------
 
! ------------------------ local variables ---------------------------
   integer ioe             !error return from fortran open
   character(len=11) ft    !format type: formatted. unformatted
   character(len=11) st    !file status: old or unknown
! --------------------------------------------------------------------
 
   if (len_trim(locfn) == 0) then
      call endrun ('(OPNFIL): local filename has zero length')
   endif
   if (form=='u' .or. form=='U') then
      ft = 'unformatted'
   else
      ft = 'formatted  '
   end if
   if ( present(status) ) then
      st = status
   else
      st = "unknown"
   end if
   open (unit=iun,file=locfn,status=st, form=ft,iostat=ioe)
   if (ioe /= 0) then
      if(masterproc) write(iulog,*)'(OPNFIL): failed to open file ',trim(locfn), ' on unit ',iun,' ierr=',ioe
      call endrun ('opnfil') 
   else
      if(masterproc) write(iulog,*)'(OPNFIL): Successfully opened file ',trim(locfn), ' on unit= ',iun
   end if
 
   return
   end subroutine opnfil
 
!=======================================================================
 
 
end module ioFileMod
